package com.javaxiaobear.module.system.mapper;

import static com.javaxiaobear.module.system.domain.table.SysMenuTableDef.SYS_MENU;
import static com.javaxiaobear.module.system.domain.table.SysRoleMenuTableDef.SYS_ROLE_MENU;
import static com.javaxiaobear.module.system.domain.table.SysRoleTableDef.SYS_ROLE;
import static com.javaxiaobear.module.system.domain.table.SysUserRoleTableDef.SYS_USER_ROLE;
import static com.javaxiaobear.module.system.domain.table.SysUserTableDef.SYS_USER;

import com.javaxiaobear.module.system.domain.SysMenu;
import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.query.QueryWrapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;

/**
 * 菜单表 数据层
 *
 * @author javaxiaobear
 */
public interface SysMenuMapper extends BaseMapper<SysMenu> {
  /** 查询系统菜单列表 */
  default List<SysMenu> selectMenuList(SysMenu menu) {
    QueryWrapper queryWrapper =
        QueryWrapper.create()
            .where(SYS_MENU.MENU_ID.isNotNull())
            .and(
                SYS_MENU
                    .MENU_NAME
                    .like(menu.getMenuName())
                    .when(menu.getMenuName() != null && !menu.getMenuName().isEmpty()))
            .and(
                SYS_MENU
                    .VISIBLE
                    .eq(menu.getVisible())
                    .when(menu.getVisible() != null && !menu.getVisible().isEmpty()))
            .and(
                SYS_MENU
                    .STATUS
                    .eq(menu.getStatus())
                    .when(menu.getStatus() != null && !menu.getStatus().isEmpty()))
            .orderBy(SYS_MENU.PARENT_ID.asc(), SYS_MENU.ORDER_NUM.asc());
    return selectListByQuery(queryWrapper);
  }

  /** 查询所有权限 */
  default List<String> selectMenuPerms() {
    return QueryChain.of(this)
        .select(SYS_MENU.PERMS)
        .from(SYS_MENU)
        .leftJoin(SYS_ROLE_MENU)
        .on(SYS_MENU.MENU_ID.eq(SYS_ROLE_MENU.MENU_ID))
        .leftJoin(SYS_USER_ROLE)
        .on(SYS_ROLE_MENU.ROLE_ID.eq(SYS_USER_ROLE.ROLE_ID))
        .listAs(String.class);
  }

  /** 根据用户查询系统菜单列表 */
  default List<SysMenu> selectMenuListByUserId(SysMenu menu) {

    return QueryChain.of(this)
        .select(
            SYS_MENU.MENU_ID,
            SYS_MENU.PARENT_ID,
            SYS_MENU.MENU_NAME,
            SYS_MENU.PATH,
            SYS_MENU.COMPONENT,
            SYS_MENU.QUERY,
            SYS_MENU.VISIBLE,
            SYS_MENU.STATUS,
            SYS_MENU.PERMS,
            SYS_MENU.IS_FRAME,
            SYS_MENU.IS_CACHE,
            SYS_MENU.MENU_TYPE,
            SYS_MENU.ICON,
            SYS_MENU.ORDER_NUM,
            SYS_MENU.CREATE_TIME)
        .from(SYS_MENU)
        .leftJoin(SYS_ROLE_MENU)
        .on(SYS_MENU.MENU_ID.eq(SYS_ROLE_MENU.MENU_ID))
        .leftJoin(SYS_USER_ROLE)
        .on(SYS_ROLE_MENU.ROLE_ID.eq(SYS_USER_ROLE.ROLE_ID))
        .leftJoin(SYS_ROLE)
        .on(SYS_USER_ROLE.ROLE_ID.eq(SYS_ROLE.ROLE_ID))
        .where(SYS_USER_ROLE.USER_ID.eq(menu.getParams().get("userId")))
        .and(
            SYS_MENU
                .MENU_NAME
                .like(menu.getMenuName())
                .when(menu.getMenuName() != null && !menu.getMenuName().isEmpty()))
        .and(
            SYS_MENU
                .VISIBLE
                .eq(menu.getVisible())
                .when(menu.getVisible() != null && !menu.getVisible().isEmpty()))
        .and(
            SYS_MENU
                .STATUS
                .eq(menu.getStatus())
                .when(menu.getStatus() != null && !menu.getStatus().isEmpty()))
        .orderBy(SYS_MENU.PARENT_ID.asc(), SYS_MENU.ORDER_NUM.asc())
        .list();
  }

  /** 根据用户ID查询权限 */
  default List<String> selectMenuPermsByUserId(Long userId) {
    return QueryChain.of(this)
        .select(SYS_MENU.PERMS)
        .from(SYS_MENU)
        .leftJoin(SYS_ROLE_MENU)
        .on(SYS_MENU.MENU_ID.eq(SYS_ROLE_MENU.MENU_ID))
        .leftJoin(SYS_USER_ROLE)
        .on(SYS_ROLE_MENU.ROLE_ID.eq(SYS_USER_ROLE.ROLE_ID))
        .leftJoin(SYS_ROLE)
        .on(SYS_ROLE.ROLE_ID.eq(SYS_USER_ROLE.ROLE_ID))
        .where(SYS_MENU.STATUS.eq("0"))
        .and(SYS_ROLE.STATUS.eq("0"))
        .and(SYS_USER_ROLE.USER_ID.eq(userId))
        .listAs(String.class);
  }

  /** 根据角色ID查询权限 */
  default List<String> selectMenuPermsByRoleId(Long roleId) {
    return QueryChain.of(this)
        .select(SYS_MENU.PERMS)
        .from(SYS_MENU)
        .leftJoin(SYS_ROLE_MENU)
        .on(SYS_MENU.MENU_ID.eq(SYS_ROLE_MENU.MENU_ID))
        .where(SYS_MENU.STATUS.eq("0"))
        .and(SYS_ROLE_MENU.ROLE_ID.eq(roleId))
        .listAs(String.class);
  }

  /** 查询所有菜单树 */
  default List<SysMenu> selectMenuTreeAll() {
    return QueryChain.of(this)
        .select(
            SYS_MENU.MENU_ID,
            SYS_MENU.PARENT_ID,
            SYS_MENU.MENU_NAME,
            SYS_MENU.PATH,
            SYS_MENU.COMPONENT,
            SYS_MENU.QUERY,
            SYS_MENU.VISIBLE,
            SYS_MENU.STATUS,
            SYS_MENU.PERMS,
            SYS_MENU.IS_FRAME,
            SYS_MENU.IS_CACHE,
            SYS_MENU.MENU_TYPE,
            SYS_MENU.ICON,
            SYS_MENU.ORDER_NUM,
            SYS_MENU.CREATE_TIME)
        .from(SYS_MENU)
        .where(SYS_MENU.MENU_TYPE.in("M", "C"))
        .and(SYS_MENU.STATUS.eq(0))
        .orderBy(SYS_MENU.PARENT_ID.asc(), SYS_MENU.ORDER_NUM.asc())
        .list();
  }

  /** 根据用户ID查询菜单树 */
  default List<SysMenu> selectMenuTreeByUserId(Long userId) {
    return QueryChain.of(this)
        .select(
            SYS_MENU.MENU_ID,
            SYS_MENU.PARENT_ID,
            SYS_MENU.MENU_NAME,
            SYS_MENU.PATH,
            SYS_MENU.COMPONENT,
            SYS_MENU.QUERY,
            SYS_MENU.VISIBLE,
            SYS_MENU.STATUS,
            SYS_MENU.PERMS,
            SYS_MENU.IS_FRAME,
            SYS_MENU.IS_CACHE,
            SYS_MENU.MENU_TYPE,
            SYS_MENU.ICON,
            SYS_MENU.ORDER_NUM,
            SYS_MENU.CREATE_TIME)
        .from(SYS_MENU)
        .leftJoin(SYS_ROLE_MENU)
        .on(SYS_MENU.MENU_ID.eq(SYS_ROLE_MENU.MENU_ID))
        .leftJoin(SYS_USER_ROLE)
        .on(SYS_ROLE_MENU.ROLE_ID.eq(SYS_USER_ROLE.ROLE_ID))
        .leftJoin(SYS_ROLE)
        .on(SYS_USER_ROLE.ROLE_ID.eq(SYS_ROLE.ROLE_ID))
        .leftJoin(SYS_USER)
        .on(SYS_USER_ROLE.USER_ID.eq(SYS_USER.USER_ID))
        .where(SYS_USER.USER_ID.eq(userId))
        .and(SYS_MENU.MENU_TYPE.in("M", "C"))
        .and(SYS_MENU.STATUS.eq(0))
        .and(SYS_ROLE.STATUS.eq(0))
        .orderBy(SYS_MENU.PARENT_ID.asc(), SYS_MENU.ORDER_NUM.asc())
        .list();
  }

  /** 根据角色ID查询菜单列表 */
  default List<Long> selectMenuListByRoleId(
      @Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly) {
    var query =
        QueryChain.of(this)
            .select(SYS_MENU.MENU_ID)
            .from(SYS_MENU)
            .leftJoin(SYS_ROLE_MENU)
            .on(SYS_MENU.MENU_ID.eq(SYS_ROLE_MENU.MENU_ID))
            .where(SYS_ROLE_MENU.ROLE_ID.eq(roleId));

    if (menuCheckStrictly) {
      query.and(
          SYS_MENU.MENU_ID.notIn(
              QueryWrapper.create()
                  .select(SYS_MENU.PARENT_ID)
                  .from(SYS_MENU)
                  .innerJoin(SYS_ROLE_MENU)
                  .on(SYS_MENU.MENU_ID.eq(SYS_ROLE_MENU.MENU_ID))
                  .where(SYS_ROLE_MENU.ROLE_ID.eq(roleId))));
    }

    return query.orderBy(SYS_MENU.PARENT_ID.asc(), SYS_MENU.ORDER_NUM.asc()).listAs(Long.class);
  }

  /** 根据菜单ID查询信息 */
  default SysMenu selectMenuById(Long menuId) {
    return QueryChain.of(this).where(SYS_MENU.MENU_ID.eq(menuId)).one();
  }

  /** 判断是否存在菜单子节点 */
  default int hasChildByMenuId(Long menuId) {
    return (int) QueryChain.of(this).where(SYS_MENU.PARENT_ID.eq(menuId)).count();
  }

  /** 新增菜单信息 */
  default int insertMenu(SysMenu menu) {
    return insert(menu);
  }

  /** 修改菜单信息 */
  default int updateMenu(SysMenu menu) {
    return update(menu);
  }

  /** 删除菜单管理信息 */
  default int deleteMenuById(Long menuId) {
    return deleteById(menuId);
  }

  /** 校验菜单名称是否唯一 */
  default SysMenu checkMenuNameUnique(
      @Param("menuName") String menuName, @Param("parentId") Long parentId) {
    return QueryChain.of(this)
        .where(SYS_MENU.MENU_NAME.eq(menuName))
        .and(SYS_MENU.PARENT_ID.eq(parentId))
        .limit(1)
        .one();
  }
}
